package com.coin900.coin.server.coin.ctrl;

import com.coin900.coin.base.AjaxResponse;
import com.coin900.coin.base.CoinConstants;
import com.coin900.coin.base.FuConstants;
import com.coin900.coin.base.utils.GoogleAuthenticator;
import com.coin900.coin.base.utils.NumberArithmeticUtils;
import com.coin900.coin.base.utils.RequestUtil;
import com.coin900.coin.persist.coin.CoinOrderVO;
import com.coin900.coin.persist.coin.CoinProjectCoinVO;
import com.coin900.coin.persist.coin.CoinProjectVO;
import com.coin900.coin.persist.coin.CoinTokenCoinVO;
import com.coin900.coin.persist.fu.FuUserVO;
import com.coin900.coin.persist.fu.FuUserWalletVO;
import com.coin900.coin.service.coin.ICoinOrderService;
import com.coin900.coin.service.coin.ICoinProjectCoinService;
import com.coin900.coin.service.coin.ICoinProjectService;
import com.coin900.coin.service.coin.ICoinTokenCoinService;
import com.coin900.coin.service.fu.IFuSmsService;
import com.coin900.coin.service.fu.IFuUserWalletService;
import com.value.exception.BusinessException;
import com.value.mybatis.Pagination;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.jws.WebParam;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 订单
 *
 * @author shui
 * @create 2018-01-16
 **/
@Controller
public class CoinOrderCtrl extends CoinController {

    /**
     * 生成订单
     *
     * @param coinOrderVO
     * @param request
     * @return 订单信息
     */
    @RequestMapping(value = "/order", method = RequestMethod.POST)
    public ModelAndView create(@RequestBody CoinOrderVO coinOrderVO,
                               HttpServletRequest request) {

        FuUserVO user = super.getUser();

        // 项目是否存在，已经发布
        Long projectId = coinOrderVO.getProjectId();
        Map<String, Object> params = new HashMap<>();
        params.put("id", projectId);
        params.put("dataStatus", 1);
        List<CoinProjectVO> coinProjectVOS = coinProjectService.loadCoinProject(params);
        if (coinProjectVOS.isEmpty()) {
            throw new BusinessException("项目不存在");
        }

        CoinProjectVO coinProjectVO = coinProjectVOS.get(0);
        // 项目状态，0未发布 1进行中 2即将 3已结束
        Double discount = 0d;
        Integer type = null;
        Integer status = coinProjectVO.getStatus();
        switch (status) {
            case CoinConstants.COIN_PROJECT_STATUS_UNPUBLISHED:
                throw new BusinessException("项目未发布");
            case CoinConstants.COIN_PROJECT_STATUS_ING:
                // 进行中
                discount = 1d;
                type = 1;
                break;
            case CoinConstants.COIN_PROJECT_STATUS_WAITING:
                // 预售
                discount = coinProjectVO.getDiscount();
                type = 2;
                break;
            default:
                break;
        }

        // 确认订单值是否正确
        Long coinId = coinOrderVO.getCoinId();
        Double tokenNumber = coinOrderVO.getTokenNumber();
        Double coinNumber = coinOrderVO.getCoinNumber();
        params.clear();
        params.put("tokenId", coinProjectVO.getTokenId());
        params.put("coinId", coinId);
        params.put("dataStatus", 1);

        List<CoinTokenCoinVO> coinTokenCoinVOS = this.tokenCoinService.loadCoinTokenCoin(params);
        CoinTokenCoinVO coinTokenCoinVO = coinTokenCoinVOS.get(0);
        Double proportion = coinTokenCoinVO.getProportion();
        BigDecimal calTokenNumber = NumberArithmeticUtils.safeMultiply(coinNumber * discount, proportion);
        if (calTokenNumber.compareTo(BigDecimal.valueOf(tokenNumber)) != 0) {
            throw new BusinessException("订单金额错误");
        }


        coinOrderVO.setType(type);
        coinOrderVO.setUserId(user.getId());
        coinOrderVO.setCreatedInfor(user);
        this.orderService.insertCoinOrder(coinOrderVO);

        AjaxResponse response = super.buildAjaxResponse(request);
        params.clear();
        params.put("id", coinOrderVO.getId());
        params.put("dataStatus", 1);
        List<CoinOrderVO> coinOrderVOS = this.orderService.loadCoinOrder(params);
        CoinOrderVO dbCoinOrder = coinOrderVOS.get(0);
        response.addModel(dbCoinOrder);
        return response.getMav();
    }

    /**
     * 返回订单页
     *
     * @param viewType
     * @param id
     * @param request
     * @return
     */
    @RequestMapping(value = "/order/{id}", method = RequestMethod.GET)
    public ModelAndView orderDetail(@PathVariable Long id,
                                    @RequestParam(required = false) String viewType,
                                    HttpServletRequest request) {

        if (CoinConstants.COIN_PAGE.equals(viewType)) {
            // 获取项目名称、虚拟币名称等数据
            ModelAndView modelAndView = buildView(request, "XXX");
            Map<String, Object> params = new HashMap<>();
            params.clear();
            params.put("id", id);
            params.put("dataStatus", 1);
            List<CoinOrderVO> coinOrderVOS = this.orderService.loadCoinOrder(params);
            CoinOrderVO dbCoinOrder = coinOrderVOS.get(0);
            modelAndView.addObject("order", dbCoinOrder);
            return modelAndView;
        }
        return null;
    }

    /**
     * 订单列表
     *
     * @param viewType
     * @param request
     * @return
     */
    @RequestMapping(value = "/order", method = RequestMethod.GET)
    public ModelAndView list(@RequestParam(required = false) String viewType,
                             HttpServletRequest request) {

        if (CoinConstants.COIN_PAGE.equals(viewType)) {
            // 获取项目名称、虚拟币名称等数据
            ModelAndView modelAndView = buildView(request, "project/order-list");
            return modelAndView;
        }

        AjaxResponse response = super.buildAjaxResponse(request);
        Pagination pagination = RequestUtil.buildPage(request);
        FuUserVO user = super.getUser();
        Map<String, Object> params = pagination.getParams();
        params.put("dataStatus", 1);
        params.put("userId", user.getId());
        List<CoinOrderVO> orderList = this.orderService.loadCoinOrderForPage(pagination);
        for (CoinOrderVO coinOrderVO : orderList) {
            Integer orderStatus = coinOrderVO.getOrderStatus();
            coinOrderVO.setOrderStatusName(CoinConstants.COIN_ORDER_STATUS.get(orderStatus));
        }
        pagination.setResults(orderList);
        response.addPagination(pagination);
        return response.getMav();
    }

    /**
     * 支付订单
     *
     * @param id
     * @param request
     * @return
     */
    @RequestMapping(value = "/order", method = RequestMethod.PATCH)
    public ModelAndView pay(@RequestParam String id,
                            @RequestParam String verifyCode,
                            @RequestParam Integer verifyType,
                            HttpServletRequest request) {

        FuUserVO user = super.getUser();
        Long userId = user.getId();
        // 确认订单是否存在
        Map<String, Object> params = new HashMap<>();
        params.put("id", id);
        params.put("dataStatus", 1);
        params.put("orderStatus", CoinConstants.COIN_ORDER_STATUS_NOT_PAID);
        List<CoinOrderVO> coinOrderVOS = this.orderService.loadCoinOrder(params);
        if (coinOrderVOS.isEmpty()) {
            throw new BusinessException("订单不存在或已支付或已取消");
        }
        CoinOrderVO coinOrderVO = coinOrderVOS.get(0);
        Long coinId = coinOrderVO.getCoinId();
        Double coinNumber = coinOrderVO.getCoinNumber();

        //支付验证
        if(verifyType== FuConstants.VERIFY_TYPE_SMS){
            String key = CoinConstants.COIN_SMS_CODE_ORDER_PAY;
            if (!this.smsService.verifyCode(verifyCode, key, user.getMobile())) {
                throw new BusinessException("验证码错误");
            }
        }else{
            Long code=Long.parseLong(verifyCode);
            Boolean verify = GoogleAuthenticator.verify(code, user.getGoogleSecret());
            if (!verify) {
                throw new BusinessException("验证码错误");
            }
        }

        // 确认用户对应虚拟币的余额是否足够
        FuUserWalletVO userWallet = this.walletService.getUserWallet(userId, coinId);
        if (userWallet == null) {
            throw new BusinessException("没有相关虚拟币钱包");
        }
        Double balance = userWallet.getBalance();
        if (balance < coinNumber) {
            throw new BusinessException("余额不足需要进行充值");
        }
        // 扣款，订单支付成功
        userWallet.setModifiedInfor(user);
        coinOrderVO.setModifiedInfor(user);
        coinOrderVO.setOrderStatus(CoinConstants.COIN_ORDER_STATUS_PAID);
        coinOrderVO.setPayDate(coinOrderVO.getModifiedDate());
        this.orderService.doPayForTheOrder(coinOrderVO, userWallet);

        params.clear();
        params.put("id", id);
        params.put("dataStatus", 1);
        List<CoinOrderVO> dbCoinOrderVOS = this.orderService.loadCoinOrder(params);
        ModelAndView modelAndView = new ModelAndView();
        CoinOrderVO dbCoinOrder = dbCoinOrderVOS.get(0);
        modelAndView.addObject("order", dbCoinOrder);
        return modelAndView;
    }

    @Autowired
    private IFuUserWalletService walletService;
    @Autowired
    private ICoinTokenCoinService tokenCoinService;
    @Autowired
    private ICoinOrderService orderService;
    @Autowired
    private ICoinProjectService coinProjectService;
    @Autowired
    private IFuSmsService smsService;
}
